﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace SuperSqlOperation.SqlServer
{

    /// <summary>
    /// 插入sql数据  OK
    /// </summary>
    static class InsertSqlExecute
    {
        /// <summary>
        ///   插入数据操作
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="conn"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public static async Task<int> InsertExecute<T>(this IDbConnection conn, T t) where T : class
        {
            PropertyInfo[] propertyInfo = t.GetType().GetProperties();
            StringBuilder cloumnStr = new StringBuilder();
            List<SqlParameter> par = new List<SqlParameter>();
            foreach (PropertyInfo property in propertyInfo)
            {
                if (!property.PropertyType.IsValueType && !property.PropertyType.Equals(typeof(string))) continue;  //过滤掉泛型以及非基础类型的数据类型
                if (property.GetDataIgnoreByAttr()) continue;  //过滤掉特性定义的需要忽略的属性
                if (!property.GetDataWriteByAttr()) continue;  //过滤掉特性定义的是否可写的属性 定义为false则忽略
                if (property.GetDataKeyByAttr()) continue;  //这里我们是insert所以过滤掉主键

                string columnName = property.GetDataColumnByAttr();
                var columnValue = property.GetValue(t) == null ? DBNull.Value : property.GetValue(t);
                cloumnStr.Append("@" + columnName + ",");
                par.Add(new SqlParameter(columnName, columnValue));
            }
            string tableName = t.GetType().GetDataTableNameByAttr();  //获得特性定义的表名称
            //sql
            string sqlCommandText =
                    string.Format("INSERT INTO {0} VALUES ({1})", tableName, cloumnStr.ToString().TrimEnd(',')); ;

            int insertId = 0;
            using (conn)
            {
                try
                {
                    SqlCommand comm = conn.CreateCommand() as SqlCommand;
                    comm.CommandText = sqlCommandText;
                    comm.Parameters.AddRange(par.ToArray());

                    conn.Open();
                    //insertId = await Task.Run(() => comm.ExecuteNonQuery());
                    insertId = await comm.ExecuteNonQueryAsync();
                    conn.Close();
                }
                catch (Exception)
                {
                    conn.Close();
                    insertId = -404; 
                } 
                return insertId;
            }
        }

        /// <summary>
        /// 批量异步 插入数据操作
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="conn"></param>
        /// <param name="ts"></param>
        /// <returns></returns>
        public static async Task<IEnumerable<int>> InsertExecute<T>(this IDbConnection conn, IEnumerable<T> ts) where T : class
        {
            PropertyInfo[] propertyInfo = ts.First().GetType().GetProperties();
            List<int> insertIds = new List<int>();
            List<SqlCommand> sqlCommands = new List<SqlCommand>();

            using (conn)
            {
                foreach (T t in ts)
                {
                    StringBuilder cloumnStr = new StringBuilder();
                    List<SqlParameter> par = new List<SqlParameter>();
                    foreach (PropertyInfo property in propertyInfo)
                    {
                        if (!property.PropertyType.IsValueType && !property.PropertyType.Equals(typeof(string))) continue;  //过滤掉泛型以及非基础类型的数据类型
                        if (property.GetDataIgnoreByAttr()) continue;  //过滤掉特性定义的需要忽略的属性
                        if (!property.GetDataWriteByAttr()) continue;  //过滤掉特性定义的是否可写的属性 定义为false则忽略
                        if (property.GetDataKeyByAttr()) continue;  //这里我们是insert所以过滤掉主键

                        string columnName = property.GetDataColumnByAttr();
                        var columnValue = property.GetValue(t) == null ? DBNull.Value : property.GetValue(t);
                        cloumnStr.Append("@" + columnName + ",");
                        par.Add(new SqlParameter(columnName, columnValue));
                    }
                    string tableName = t.GetType().GetDataTableNameByAttr();  //获得特性定义的表名称


                    SqlCommand comm = conn.CreateCommand() as SqlCommand;
                    comm.CommandText =
                        string.Format("INSERT INTO {0} VALUES ({1})", tableName, cloumnStr.ToString().TrimEnd(','));
                    comm.Parameters.AddRange(par.ToArray());
                    sqlCommands.Add(comm);
                }

                conn.Open();
                foreach (SqlCommand comm in sqlCommands)
                {
                    //int insertId = await Task.Run(() => comm.ExecuteNonQuery());
                    int insertId = await comm.ExecuteNonQueryAsync();
                    // insertId = await comm.ExecuteNonQueryAsync();
                    //Task<int>  task = new Task<int>(()=> { return comm.ExecuteNonQuery(); });
                    //task.Start();
                    //int insertId = task.Result;
                    //int insertId = comm.ExecuteNonQuery();
                    insertIds.Add(insertId);
                }

                IEnumerable<int> ttt = insertIds;
                return ttt;
            }
        }
    }

}
